/**
 * 
 */
package br.com.games.hefesto.board;

import br.com.games.hefesto.Game;
import br.com.games.hefesto.Player;
import br.com.games.hefesto.Team;

/**
 * Gerencia uma partida de tabulero
 * 
 * @param <Sqr>
 *            Tipo que constituirá o tabulero
 * @param <Moveable>
 *            Tipo que será laçado
 * 
 * @since 2013
 * @author <li><em>fernando.schindler@gmail.com</em></li>
 */
public abstract class BoardGame<Sqr, Moveable> implements
		Game<Board<Sqr>, Moveable> {

	/**
	 * Criar um gerenciador de partida
	 * 
	 * @param board
	 * @param players
	 */
	public BoardGame(Board<Sqr> board,
			Player<? extends Board<Sqr>, Moveable>... players) {
		this.state = board;
		this.players = players;
		this.current = 0;
		this.initialTeam = players[0].getTeam();
	}

	/**
	 * Passa para o próximo jogador
	 */
	protected void nextPlayer() {
		this.current++;
	}

	/**
	 * Jogador anterior
	 */
	protected void prevPlayer() {
		this.current--;
	}

	/**
	 * Recuperar todos os jogadores
	 * 
	 * @return
	 */
	public Player<? extends Board<Sqr>, Moveable>[] getPlayers() {
		return this.players;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see br.com.games.hefesto.Game#getCurrent()
	 */
	@SuppressWarnings("unchecked")
	@Override
	public Player<Board<Sqr>, Moveable> getCurrent() {
		return (Player<Board<Sqr>, Moveable>) this.players[this.current
				% this.players.length];
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see br.com.games.hefesto.Game#getState()
	 */
	@Override
	public Board<Sqr> getState() {
		return this.state;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see br.com.games.hefesto.Game#reset()
	 */
	@Override
	public void reset() {
		this.current = 0;
		this.state.reset();
		while (!getCurrent().getTeam().equals(this.initialTeam)){
			nextPlayer();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see br.com.games.hefesto.Game#setFirstTeam(br.com.games.hefesto.Team)
	 */
	@Override
	public void setFirstTeam(Team team) {
		for (Player<?, ?> p : players)
			if (p.getTeam().equals(team)) {
				this.initialTeam = team;
				break;
			}
	}

	/**
	 * Campos privados
	 */
	protected Board<Sqr> state;
	protected Player<? extends Board<Sqr>, Moveable> players[];
	private int current;
	private Team initialTeam;
}
